package com.zhouyu.fileSync.FScommon.api;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Charsets;
import com.zhouyu.fileSync.FScommon.api.entities.Response;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.AttributeKey;

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;

/**
 * Created by zhouyu@lightinthebox.com on 2019/8/14
 **/
public class FileAndJsonDecoder extends ChannelInboundHandlerAdapter {

    private String tmpPath;

    public FileAndJsonDecoder(String tmpPath) {
        this.tmpPath = tmpPath;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object in) throws Exception {
        if (in instanceof  ByteBuf){
            ByteBuf decode= (ByteBuf) in;
            AttributeKey fileChannel =null;
            if ( AttributeKey.exists("fileChannel")){
                fileChannel =AttributeKey.valueOf("fileChannel");
            }else {
                fileChannel =AttributeKey.newInstance("fileChannel");
            }
            AttributeKey rFile =null;
            if ( AttributeKey.exists("rFile")){
                rFile =AttributeKey.valueOf("rFile");
            }else {
                rFile =AttributeKey.newInstance("rFile");
            }

            String header=getHeadInfo(decode);
            if (header.startsWith("RESPONSE:")){
                ctx.fireChannelRead( JSON.parseObject(decode.toString(Charset.forName("UTF-8")).substring(45), Response.class));
            }else if (header.startsWith("FILE:")){
                Response response=new Response();
                String headInfo=decode.slice(0,74).toString(Charset.forName("UTF-8"));
                String[] infos=headInfo.split(":");
                response.setRequestId(infos[1]);
                String md5=infos[2];
                String filePath=tmpPath+System.currentTimeMillis();
                File result = new File(filePath);
                if (!result.exists()) {
                    result.createNewFile();
                }
                RandomAccessFile destFile = new RandomAccessFile(result, "rw");
                ctx.channel().attr(rFile).set(destFile);
                FileChannel destFileChannel = destFile.getChannel();
                destFileChannel.tryLock();
                String end=decode.slice(decode.readableBytes()-10,10).toString(Charset.defaultCharset());
                if ("_FILE_END_".equals(end)) {
                    destFileChannel.write(decode.slice(74,decode.readableBytes()-84).nioBuffer());
                    destFileChannel.close();
                    ((RandomAccessFile)ctx.channel().attr(rFile).get()).close();
                    System.out.println("文件关闭");
                }else {
                    destFileChannel.write(decode.slice(74,decode.readableBytes()-74).nioBuffer());
                    ctx.channel().attr(fileChannel).set(destFileChannel);
                }
                response.setData(result);
                response.setMd5(md5);
                ctx.fireChannelRead(response);
            }else {
                FileChannel destFileChannel= (FileChannel) ctx.channel().attr(fileChannel).get();
                String end=null;
                if (decode.readableBytes()>10){
                    end=decode.slice(decode.readableBytes()-10,10).toString(Charset.defaultCharset());
                    if ("_FILE_END_".equals(end)) {
                        destFileChannel.write(decode.slice(0,decode.readableBytes()-10).nioBuffer());
                        destFileChannel.close();
                        ((RandomAccessFile)ctx.channel().attr(rFile).get()).close();
                        System.out.println("文件关闭");
                        ctx.channel().attr(fileChannel).set(null);
                    }else {
                        destFileChannel.write(decode.nioBuffer());
                    }
                }else {
                    end=decode.toString(Charset.defaultCharset());
                    if ("_FILE_END_".equals(end)) {
                        destFileChannel.close();
                        ((RandomAccessFile)ctx.channel().attr(rFile).get()).close();
                        System.out.println("文件关闭");
                        ctx.channel().attr(fileChannel).set(null);
                    }else {
                        destFileChannel.write(decode.nioBuffer());
                    }
                }
            }

        }
    }

    private String getHeadInfo(ByteBuf buffer) {
        if (buffer.readableBytes()<10){
            return "content";
        }else {
            ByteBuf head = buffer.slice(0, 10);
            return head.toString(Charsets.UTF_8);
        }
    }


}
